// src/utils/interpreter.ts
import * as acorn from "acorn";

/** ---------- 作用域变量与作用域管理 ---------- */
class ScopeVar {
	kind : "var" | "let" | "const";
	value : any;
	constructor(kind : "var" | "let" | "const", value : any) {
		this.kind = kind;
		this.value = value;
	}
	$set(v : any) {
		if (this.kind === "const") throw new Error("Assignment to constant variable");
		this.value = v;
	}
	$get() {
		return this.value;
	}
}

class Scope {
	parent : Scope | null;
	table : Record<string, ScopeVar> = {};
	isAsyncContext : boolean = false; // 是否允许异步操作（如await）
	isTopLevel : boolean = false; // 是否为顶层作用域（模块级）

	constructor(parent : Scope | null = null, isAsyncContext : boolean = false, isTopLevel : boolean = false) {
		this.parent = parent;
		this.isAsyncContext = isAsyncContext;
		this.isTopLevel = isTopLevel;
	}
	find(name : string) : ScopeVar | null {
		if (Object.prototype.hasOwnProperty.call(this.table, name)) {
			return this.table[name];
		}
		return this.parent ? this.parent.find(name) : null;
	}
	declare(kind : "var" | "let" | "const", name : string, value : any) {
		if (!this.table[name]) {
			this.table[name] = new ScopeVar(kind, value);
		}
	}
	createChild(isAsync ?: boolean, isTopLevel ?: boolean) : Scope {
		return new Scope(
			this,
			isAsync ?? this.isAsyncContext,
			isTopLevel ?? this.isTopLevel
		);
	}
}

/** ---------- 包装 setTimeout ---------- */
const hostSetTimeout = (globalThis as any).setTimeout;
function wrappedSetTimeout(cb : any, delay ?: number, ...args : any[]) {
	if (typeof cb === "function") {
		return hostSetTimeout(cb, delay, ...args);
	}
	if (cb && cb.__node && cb.__scope) {
		return hostSetTimeout(() => {
			try {
				executeNode(cb.__node.body, new Scope(cb.__scope));
			} catch (err) {
				console.error("定时器回调出错:", err);
			}
		}, delay);
	}
	console.warn("setTimeout: 第一个参数不可调用", cb);
	return hostSetTimeout(() => { }, delay);
}

/** ---------- 默认API注入 ---------- */
const defaultApi : Record<string, any> = {
	console,
	JSON,
	Math,
	Date,
	Number,
	String,
	Boolean,
	Array,
	Object,
	clearTimeout,
	setInterval,
	clearInterval,
	setTimeout: wrappedSetTimeout,
	Promise: Promise,
};

/**
 * 判断节点是否需要异步执行
 */
function shouldUseAsync(node : any, scope ?: Scope) : boolean {
	if (!node) return false;

	// 明确需要异步的节点类型
	if (node.type === "AwaitExpression") return true;

	// 异步函数相关节点
	if ((node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression") && node.async) {
		return true;
	}

	// 递归检查子节点（关键：确保深层await被识别）
	if (typeof node === "object") {
		for (const key in node) {
			if (node[key] && typeof node[key] === "object") {
				if (Array.isArray(node[key])) {
					for (const child of node[key]) {
						if (shouldUseAsync(child, scope)) return true;
					}
				} else {
					if (shouldUseAsync(node[key], scope)) return true;
				}
			}
		}
	}

	return false;
}

/**
 * 统一执行入口，自动判断同步/异步执行
 */
async function executeNode(node : any, scope : Scope) : Promise<any> {
	try {
		if (shouldUseAsync(node, scope)) {
			return executeAsync(node, scope);
		} else {
			return executeSync(node, scope);
		}
	} catch (err : any) {
		// debugger;
		console.log(err);
		throw err;
	}
}

/** ---------- 核心执行函数（同步） ---------- */
function executeSync(node : any, scope : Scope) : any {
	switch (node.type) {
		case "UpdateExpression": {
			const arg = node.argument;
			if (arg.type === "Identifier") {
				const variable = scope.find(arg.name);
				if (!variable) throw new Error(`变量未定义: ${arg.name}`);
				let oldValue = variable.$get();

				// 根据运算符执行
				let newValue;
				switch (node.operator) {
					case "++":
						newValue = oldValue + 1;
						break;
					case "--":
						newValue = oldValue - 1;
						break;
					default:
						throw new Error(`不支持的自增自减运算符: ${node.operator}`);
				}

				// 更新作用域中的值
				variable.$set(newValue);

				// prefix 决定返回值：++i 返回新值，i++ 返回旧值
				return node.prefix ? newValue : oldValue;
			}

			// 也支持对象属性自增，如 obj.x++
			if (arg.type === "MemberExpression") {
				const obj = executeSync(arg.object, scope);
				const prop = arg.computed ? executeSync(arg.property, scope) : arg.property.name;

				let oldValue = obj[prop];
				let newValue;
				switch (node.operator) {
					case "++":
						newValue = oldValue + 1;
						break;
					case "--":
						newValue = oldValue - 1;
						break;
					default:
						throw new Error(`不支持的自增自减运算符: ${node.operator}`);
				}

				obj[prop] = newValue;
				return node.prefix ? newValue : oldValue;
			}

			throw new Error(`UpdateExpression 不支持的参数类型: ${arg.type}`);
		}

		case "ForStatement": {
			const loopScope = scope.createChild(scope.isAsyncContext);

			// 初始化部分
			if (node.init) {
				if (node.init.type === "VariableDeclaration") {
					executeSync(node.init, loopScope);
				} else {
					executeSync(node.init, loopScope);
				}
			}

			let result;
			while (true) {
				// 判断条件
				if (node.test) {
					const testVal = executeSync(node.test, loopScope);
					if (!testVal) break;
				}

				// 执行循环体
				result = executeSync(node.body, loopScope);

				// 迭代部分
				if (node.update) {
					executeSync(node.update, loopScope);
				}
			}

			return result;
		}

		case "Program": {
			let result;
			for (const stmt of node.body) {
				// 👇 注意，先判断是否需要异步，而不是执行再回退
				if (shouldUseAsync(stmt, scope)) {
					return executeAsync(node, scope);
				}
			}
			for (const stmt of node.body) {
				result = executeSync(stmt, scope);
			}
			return result;
		}
		case "ConditionalExpression": {
			const test = executeSync(node.test, scope);
			return test
				? executeSync(node.consequent, scope)
				: executeSync(node.alternate, scope);
		}


		case "EmptyStatement":
			// 空语句什么也不做，直接返回 undefined
			return;
		case "ExpressionStatement":
			return executeSync(node.expression, scope);


		case "Identifier": {
			const v = scope.find(node.name);
			if (!v) throw new Error(`变量未定义: ${node.name}`);
			return v.$get();
		}

		case "VariableDeclaration":
			for (const decl of node.declarations) {
				const initVal = decl.init ? executeSync(decl.init, scope) : undefined;
				scope.declare(node.kind, decl.id.name, initVal);
			}
			return;

		case "CallExpression": {
			if (node.callee.type === "MemberExpression") {
				const obj = executeSync(node.callee.object, scope);
				const prop = node.callee.computed
					? executeSync(node.callee.property, scope)
					: node.callee.property.name;
				const fn = obj[prop];
				const args = node.arguments.map((a : any) => executeSync(a, scope));
				if (typeof fn !== "function") throw new Error(`${prop} 不是函数`);

				return fn.call(obj, ...args);
			} else {
				const callee = executeSync(node.callee, scope);
				const args = node.arguments.map((a : any) => executeSync(a, scope));
				if (typeof callee === "function") {
					return callee(...args);
				}
				throw new Error("尝试调用的对象不是函数");
			}
		}

		case "MemberExpression": {
			const obj = executeSync(node.object, scope);
			const prop = node.computed ? executeSync(node.property, scope) : node.property.name;
			return obj[prop];
		}

		case "AssignmentExpression": {
			if (node.left.type === "Identifier") {
				const v = scope.find(node.left.name);
				if (!v) throw new Error(`变量未定义: ${node.left.name}`);
				const val = executeSync(node.right, scope);
				v.$set(val);
				return val;
			}
			if (node.left.type === "MemberExpression") {
				const obj = executeSync(node.left.object, scope);
				const prop = node.left.computed
					? executeSync(node.left.property, scope)
					: node.left.property.name;
				const val = executeSync(node.right, scope);
				obj[prop] = val;
				return val;
			}
			throw new Error("不支持的赋值类型");
		}

		case "ArrowFunctionExpression":
		case "FunctionExpression": {
			const isAsync = node.async;
			const originalScope = scope;
			const originalNode = node;
			const paramNames = node.params.map((p : any) => p.name);

			const func = isAsync
				? async (...args : any[]) => {
					const funcScope = originalScope.createChild(true);
					// 绑定参数时使用保存的参数名称数组
					paramNames.forEach((name : string, i : number) => {
						funcScope.declare("let", name, args[i]);
					});
					// console.log('funcScope:');
					// console.log(funcScope);
					// debugger;
					return await executeNode(originalNode.body, funcScope);
				}
				: (...args : any[]) => {
					const funcScope = scope.createChild(false);
					paramNames.forEach((name : string, i : number) => {
						funcScope.declare("let", name, args[i]);
					});
					return executeSync(originalNode.body, funcScope);
				};

			// 保存参数信息供外部参考
			(func as any).__params = paramNames;
			(func as any).__node = node;
			(func as any).__scope = scope;
			(func as any).__isAsync = isAsync;
			return func;

		}

		case "BlockStatement": {
			let result;
			for (const stmt of node.body) {
				if (shouldUseAsync(stmt, scope)) {
					return executeAsync(node, scope);
				}
			}
			for (const stmt of node.body) {
				if (stmt.type === "ReturnStatement") {
					return executeSync(stmt, scope);
				}
				result = executeSync(stmt, scope);
			}
			return result;
		}


		case "ReturnStatement": {
			return node.argument ? executeSync(node.argument, scope) : undefined;
		}

		case "AwaitExpression": {
			// 同步执行中遇到await直接抛出错误（应该由shouldUseAsync提前拦截）
			if (!scope.isAsyncContext) {
				throw new Error("同步函数中不允许使用await");
			}
			// 实际会由异步执行处理
			throw new Error("Unexpected await in sync execution");
		}

		case "LogicalExpression": {
			const left = executeSync(node.left, scope);
			if (node.operator === "&&") {
				return left && executeSync(node.right, scope);
			}
			if (node.operator === "||") {
				return left || executeSync(node.right, scope);
			}
			// 新增：支持空值合并运算符 ??
			if (node.operator === "??") {
				// 当左值为 null 或 undefined 时，返回右值，否则返回左值
				return left ?? executeSync(node.right, scope);
			}
			throw new Error(`不支持的逻辑运算符: ${node.operator}`);
		}

		case "UnaryExpression": {
			const arg = executeSync(node.argument, scope);
			switch (node.operator) {
				case "!": return !arg;
				case "typeof": return typeof arg;
				case "+": return +arg;
				case "-": return -arg;
				default: throw new Error(`不支持的一元运算符: ${node.operator}`);
			}
		}

		case "BinaryExpression": {
			const left = executeSync(node.left, scope);
			const right = executeSync(node.right, scope);
			switch (node.operator) {
				case "==": return left == right;
				case "!=": return left != right;
				case "===": return left === right;
				case "!==": return left !== right;
				case "<": return left < right;
				case "<=": return left <= right;
				case ">": return left > right;
				case ">=": return left >= right;
				case "+": return left + right;
				case "-": return left - right;
				case "*": return left * right;
				case "/": return left / right;
				case "%": return left % right;
				default: throw new Error(`不支持的二元运算符: ${node.operator}`);
			}
		}

		case "IfStatement": {
			const test = executeSync(node.test, scope);
			if (test) {
				return executeNode(node.consequent, scope);
			} else if (node.alternate) {
				return executeNode(node.alternate, scope);
			}
			return;
		}

		case "ObjectExpression": {
			const obj : any = {};
			for (const prop of node.properties) {
				if (prop.type === "Property") {
					const key = prop.key.type === "Identifier" ? prop.key.name : executeSync(prop.key, scope);
					const value = executeSync(prop.value, scope);
					obj[key] = value;
				} else if (prop.type === "SpreadElement") {
					const spreadValue = executeSync(prop.argument, scope);
					Object.assign(obj, spreadValue);
				}
			}
			return obj;
		}

		case "ArrayExpression": {
			const elements = [];
			for (const elem of node.elements) {
				if (elem?.type === "SpreadElement") {
					const spreadValue = executeSync(elem.argument, scope);
					if (Array.isArray(spreadValue)) {
						elements.push(...spreadValue);
					} else {
						throw new Error(`Cannot spread non-iterable value: ${spreadValue}`);
					}
				} else if (elem) {
					elements.push(executeSync(elem, scope));
				} else {
					elements.push(undefined);
				}
			}
			return elements;
		}

		case "NewExpression": {
			const constructor = executeSync(node.callee, scope);
			if (typeof constructor !== "function") {
				throw new Error("new 操作符后的对象不是构造函数");
			}

			const args = node.arguments.map((arg : any) => executeSync(arg, scope));
			return Reflect.construct(constructor, args);
		}

		case "ChainExpression": {
			const expr = node.expression;
			let value = executeSync(expr, scope);
			if (value === null || typeof value === 'undefined') {
				return undefined;
			}
			return value;
		}

		case "OptionalMemberExpression": {
			const obj = executeSync(node.object, scope);
			if (obj === null || typeof obj === 'undefined') {
				return undefined;
			}
			const prop = node.computed
				? executeSync(node.property, scope)
				: node.property.name;
			return obj[prop];
		}

		case "OptionalCallExpression": {
			const callee = executeSync(node.callee, scope);
			if (callee === null || typeof callee === 'undefined') {
				return undefined;
			}
			const args = node.arguments.map((a : any) => executeSync(a, scope));
			const context = node.callee.type === "MemberExpression"
				? executeSync((node.callee as any).object, scope)
				: undefined;
			if (typeof callee !== "function") {
				throw new Error("可选链调用的目标不是函数");
			}
			return context ? callee.call(context, ...args) : callee(...args);
		}

		case "Literal": {
			// 处理字符串中的转义字符（如\n、\t等）
			if (typeof node.value === 'string') {
				return node.value.replace(/\\n/g, '\n')
					.replace(/\\t/g, '\t')
					.replace(/\\"/g, '"')
					.replace(/\\\\/g, '\\');
			}
			return node.value;
		}

		case "TemplateLiteral": {
			// 处理模板字符串（支持多行）
			let result = '';
			// 拼接字符串片段和表达式结果
			for (let i = 0; i < node.quasis.length; i++) {
				result += node.quasis[i].value.cooked; // 包含换行的原始字符串
				if (i < node.expressions.length) {
					result += executeSync(node.expressions[i], scope);
				}
			}
			return result;
		}


		default:
			console.warn("未实现的同步AST节点类型:", node.type);
			return undefined;
	}
}

/** ---------- 核心执行函数（异步） ---------- */
async function executeAsync(node : any, scope : Scope) : Promise<any> {
	switch (node.type) {
		case "UpdateExpression": {
			const arg = node.argument;
			if (arg.type === "Identifier") {
				const variable = scope.find(arg.name);
				if (!variable) throw new Error(`变量未定义: ${arg.name}`);
				let oldValue = variable.$get();

				let newValue;
				switch (node.operator) {
					case "++":
						newValue = oldValue + 1;
						break;
					case "--":
						newValue = oldValue - 1;
						break;
					default:
						throw new Error(`不支持的自增自减运算符: ${node.operator}`);
				}

				variable.$set(newValue);
				return node.prefix ? newValue : oldValue;
			}

			if (arg.type === "MemberExpression") {
				const obj = await executeNode(arg.object, scope);
				const prop = arg.computed
					? await executeNode(arg.property, scope)
					: arg.property.name;

				let oldValue = obj[prop];
				let newValue;
				switch (node.operator) {
					case "++":
						newValue = oldValue + 1;
						break;
					case "--":
						newValue = oldValue - 1;
						break;
					default:
						throw new Error(`不支持的自增自减运算符: ${node.operator}`);
				}

				obj[prop] = newValue;
				return node.prefix ? newValue : oldValue;
			}

			throw new Error(`UpdateExpression 不支持的参数类型: ${arg.type}`);
		}

		case "ForStatement": {
			const loopScope = scope.createChild(scope.isAsyncContext);

			if (node.init) {
				if (node.init.type === "VariableDeclaration") {
					await executeNode(node.init, loopScope);
				} else {
					await executeNode(node.init, loopScope);
				}
			}

			let result;
			while (true) {
				if (node.test) {
					const testVal = await executeNode(node.test, loopScope);
					if (!testVal) break;
				}

				result = await executeNode(node.body, loopScope);

				if (node.update) {
					await executeNode(node.update, loopScope);
				}
			}

			return result;
		}

		case "Program": {
			let result;
			for (const stmt of node.body) {
				result = await executeNode(stmt, scope);
			}
			return result;
		}
		case "ConditionalExpression": {
			const test = await executeNode(node.test, scope);
			return test
				? await executeNode(node.consequent, scope)
				: await executeNode(node.alternate, scope);
		}

		case "BlockStatement": {
			let result;
			for (const stmt of node.body) {
				if (stmt.type === "ReturnStatement") {
					return await executeNode(stmt, scope);
				}
				result = await executeNode(stmt, scope);
			}
			return result;
		}
		case "EmptyStatement":
			return;

		case "ExpressionStatement":
			return await executeAsync(node.expression, scope);

		case "AwaitExpression": {
			const value = await executeNode(node.argument, scope);
			return await Promise.resolve(value);
		}

		case "CallExpression": {
			if (node.callee.type === "MemberExpression") {
				const obj = await executeNode(node.callee.object, scope);
				const prop = node.callee.computed
					? await executeNode(node.callee.property, scope)
					: node.callee.property.name;
				const fn = obj[prop];
				const args = await Promise.all(node.arguments.map((a : any) => executeNode(a, scope)));
				if (typeof fn !== "function") throw new Error(`${prop} 不是函数`);
				const result = fn.call(obj, ...args);
				return result instanceof Promise ? await result : result;
			} else {
				const callee = await executeNode(node.callee, scope);
				const args = await Promise.all(node.arguments.map((a : any) => executeNode(a, scope)));
				if (typeof callee === "function") {
					const result = callee(...args);
					return (callee as any).__isAsync ? await result : result;
				}
				throw new Error("尝试调用的对象不是函数");
			}
		}

		// 变量声明在异步执行中的处理
		case "VariableDeclaration": {
			for (const decl of node.declarations) {
				const initVal = decl.init ? await executeNode(decl.init, scope) : undefined;
				scope.declare(node.kind, decl.id.name, initVal);
			}
			return;
		}

		// 其他节点默认用同步执行（已确保无异步操作）
		default:
			return executeSync(node, scope);
	}
}

/** ---------- 解释器入口 ---------- */
export function run(
	code : string,
	appendApi : Record<string, any> = {},
	options : { ecmaVersion ?: number } = {}
) : Promise<any> {
	// 关键修改：将顶级作用域标记为异步上下文
	const scope = new Scope(null, true, true);
	Object.keys(defaultApi).forEach((k) => {
		scope.declare("const", k, (defaultApi as any)[k]);
	});
	Object.keys(appendApi).forEach((k) => {
		scope.declare("const", k, appendApi[k]);
	});

	const ast = acorn.parse(code, {
		ecmaVersion: options.ecmaVersion || 2022,
		sourceType: "module"
	}) as any;

	return executeNode(ast, scope);
}